package com.net.server.netty;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.sql.SQLException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

import com.net.server.NetServer;
import com.net.server.NetServiceStartException;
import com.net.utils.PrintUtil;
import com.utils.ThreadUtil;

public class NettyServer implements NetServer {
	public static String PROGRAM_PATH = null;
	private String bindAddr = null;
	private int port = 0;
	private ServerBootstrap acceptor = null;
	private int sessionIdleTime;
	// private SessionHandler handler;
	static ExecutionHandler executeHandler;
	private Channel serverChannel;
	private ChannelGroup allChannels = new DefaultChannelGroup();

	private volatile boolean started = false;

	public NettyServer(String bindAddr, int port) {
		if ((port < 0) || (port > 65525)) {
			throw new IllegalArgumentException("传入非法端口属性值(" + port + ",监听端口之只能在1024至65535之间)");
		}
		this.bindAddr = bindAddr;
		this.port = port;
	}

	public NettyServer(int port) {
		this(null, port);
	}

	@Override
	public void start() throws NetServiceStartException {
		acceptor = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool()));// 线程工厂
		
		// 子channel的属性集
		acceptor.setOption("child.tcpNoDelay", true);// 不启用nagle算法，Nagle算法遇到delayed
		acceptor.setOption("child.keepAlive", true);// 超过没发，发送一个ack探测包发到对方，探测双方的TCP/IP连接是否有效。
		acceptor.setOption("child.receiveBufferSize", 128 * 1024);// 设置TCP接收缓存区大小为128K,
		acceptor.setOption("child.sendBufferSize", 64 * 1024);// TCP发送缓存区
		acceptor.setOption("reuseAddress", true);// 将允许将套接字绑定到已在使用中的地址
		// acceptor.setOption("allIdleTime", getSessionIdleTime());//超时时间
		acceptor.setOption("backlog", 100);// 输入连接指示（对连接的请求）的最大队列长度。如果队列满时收到连接指示，则拒绝该连接。FIFO（先进先出）的原则
		// 用于给消息排队
		Executor orderedExecutor = new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576, 5, TimeUnit.SECONDS, ThreadUtil.createThreadFactory("executionpool"));
		executeHandler = new ExecutionHandler(orderedExecutor);

		acceptor.setPipelineFactory(new ServerPipelineFactory(getSessionIdleTime(), executeHandler));

		SocketAddress socketAddress = null;
		if ((bindAddr != null) && (!bindAddr.trim().equals("")))
			socketAddress = new InetSocketAddress(bindAddr, port);
		else {
			socketAddress = new InetSocketAddress(port);
		}
		// LoggerManager.Print.debug(" NettyServer Bind Address" + bindAddr +
		// " " + port);
		serverChannel = acceptor.bind(socketAddress);
		allChannels.add(serverChannel);
		this.setRunning(true);

		PrintUtil.info("服务器启动成功!");
	}

	@Override
	public void stop() {
		allChannels.close().awaitUninterruptibly();
		acceptor.releaseExternalResources();
		executeHandler.releaseExternalResources();
	}

	@Override
	public boolean isRunning() {
		return started;
	}

	@Override
	public void setRunning(boolean running) {
		this.started = running;
	}

	public int getSessionIdleTime() {
		return sessionIdleTime;
	}

	public void setSessionIdleTime(int sessionIdleTime) {
		this.sessionIdleTime = sessionIdleTime;
	}

	public static void main(String[] args) throws NetServiceStartException, SQLException, InstantiationException, IllegalAccessException, Exception {

		// LoggerManager.initilize();
		// Map<Integer, Protocol> map = ProtocolHelper.map;
		// LoggerManager.Print.info("####protocol num:" + map.size());

		if (System.getProperty("netty.pool.size") == null) {
			System.setProperty("netty.pool.size", "50");
		}
		System.setProperty("ibatisSql", "open");

		NettyServer socketServer = new NettyServer(9300);

		socketServer.setSessionIdleTime(1 * 60 * 60); // TODO 设定心跳的检查时间 1小时 客户端,
		// 15s心跳
		socketServer.start();

		// //同步UserProfie字段到user_profile表,如果UserProfie新增了字段并加了Property注解,则新建字段,
		// 字段比较忽略大小写
		// TableSyncUtils.syncFieldToMysql(null, UserProfile.class,
		// Constants.getConfig());
		// TableSyncUtils.closeDataSource();//检查完毕后关闭数据源

		// if (System.getProperty("file.separator").equals("\\")) {
		// ModelManager.getInstance().init("D:/opt/pgame/config.xml",
		// Constants.getNativeServerId());
		// } else {
		// String configPaht = System.getProperty("CONFIGPATH",
		// "/home/wayne/Desktop/xiaosanguo/xsg_server/trunk/pgame/config.xml");
		// ModelManager.getInstance().init(configPaht,
		// Constants.getNativeServerId());
		// }
		//
		// LocalcacheManager.getInstance().loadAllUserData();
		// StatisticManager.getInstance();
		// StatisticMessageQueue.getInstance().start();

		// 日志服务
		// LogService.getInstance().start();

		// Constants.SYSTEM_MAINTENANCE = false;
		// // 排行榜
		// ChartsCache.getInstance();
		// ShopManager.getInstance().init();
		//
		// // 全局活动缓存初始化
		// GlobalActivityInfoCache.getInstance().init();
		//
		// // 全局BOSS信息初始化
		// GlobalBossInfoCache.getInstance().init();
		//
		// // 开启httpServer
		// int httpport =
		// Integer.parseInt(Constants.getConfig().getProperty("http.server.port"));
		// HttpServer httpserver = new HttpServer();
		// httpserver.start(httpport);
		// httpserver.registerHandler();

		// 连接后台,如后台没有启动,定时连接后台
		// new Timer().schedule(new TimerTask() {
		// int count = 0;
		//
		// @Override
		// public void run() {
		// try {
		// BackendClient me = BackendClient.getMe();
		// if (!me.isConnected()) {
		// me.start();
		// if (me.isConnected()) {
		// me.register();
		// LoggerManager.Backend.error("连接后台服务器 : " + me.isConnected());
		// }
		// }
		// } catch (Exception e) {
		// if ((count++ % 30) == 0) {
		// LoggerManager.Backend.error("连接后台异常 ", e);
		// }
		// }
		//
		// }
		// }, 0, BackendClient.backendCheckTime * 1000);
		//
		// MerchantActivityManager.getInstance().init();
		//
		// LoggerManager.Print.info("========= 服务器启动成功 ！ =========");

		// 根据平台启动时初始化
		// Platform platform = Constants.getPlatform();
		// PlatformService platformService = platform.getPlatformService();
		// if(platformService != null) {
		// platformService.initPlatform();
		// }else {
		// if(Constants.getConfig().getProperty("testPay",
		// "false").equals("true")) {
		// Platform.LEDOU.getPlatformService().initPlatform();
		// }
		// }
		// TODO 需要充值服务再开启
		// RechargeService.getService().start();
	}

}
